package com.ssy.lingxi.order.serviceimpl.web;

import com.querydsl.core.group.GroupBy;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.basic.EnableDisableStatus;
import com.ssy.lingxi.common.constant.member.MemberLevelTypeEnum;
import com.ssy.lingxi.common.constant.member.RoleTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderPayChannelEnum;
import com.ssy.lingxi.common.constant.order.OrderTradeProcessTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderTypeEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.order.entity.*;
import com.ssy.lingxi.order.model.bo.PlatformPayTypeBO;
import com.ssy.lingxi.order.model.bo.VendorBO;
import com.ssy.lingxi.order.model.constant.OrderOuterStatusEnum;
import com.ssy.lingxi.order.model.constant.OrderServiceContants;
import com.ssy.lingxi.order.model.dto.VendorLogoDTO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderIdVO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderNoVO;
import com.ssy.lingxi.order.model.vo.basic.request.ShopIdPageVO;
import com.ssy.lingxi.order.model.vo.basic.response.OrderPayChannelDetailVO;
import com.ssy.lingxi.order.model.vo.common.request.*;
import com.ssy.lingxi.order.model.vo.common.response.*;
import com.ssy.lingxi.order.model.vo.vendor.response.VendorOrderDetailVO;
import com.ssy.lingxi.order.repository.OrderRepository;
import com.ssy.lingxi.order.service.base.IBaseCacheService;
import com.ssy.lingxi.order.service.base.IBaseOrderHistoryService;
import com.ssy.lingxi.order.service.base.IBaseOrderProcessService;
import com.ssy.lingxi.order.service.base.IBaseOrderService;
import com.ssy.lingxi.order.service.feign.IPlatformTemplateFeignService;
import com.ssy.lingxi.order.service.web.IOrderCommonService;
import com.ssy.lingxi.order.utils.NumberUtil;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 订单相关的其他接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-07-29
 */
@Service
public class OrderCommonServiceImpl implements IOrderCommonService {
    @Resource
    private IBaseCacheService baseCacheService;

    @Resource
    private IPlatformTemplateFeignService platformTemplateFeignService;

    @Resource
    private IBaseOrderHistoryService baseOrderHistoryService;

    @Resource
    private IBaseOrderProcessService baseOrderProcessService;

    @Resource
    private JPAQueryFactory jpaQueryFactory;

    @Resource
    private IBaseOrderService baseOrderService;

    @Resource
    private OrderRepository orderRepository;

    /**
     * 商城首页 - 分页查询商品交易记录
     *
     * @param headers   HttpHeaders信息
     * @param historyVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<OrderProductHistoryQueryVO>> pageOrderProductHistories(HttpHeaders headers, OrderProductHistoryVO historyVO) {
        return baseOrderHistoryService.pageOrderProductHistories(historyVO);
    }

    /**
     * 商城首页 - 分页查询商品成交动态
     *
     * @param headers HttpHeaders信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<OrderProductShopHistoryVO>> pageOrderProductShopHistories(HttpHeaders headers, ShopIdPageVO pageVO) {
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderDO qOrder = QOrderDO.orderDO;
        JPAQuery<OrderProductShopHistoryVO> query = jpaQueryFactory
                .select(Projections.constructor(OrderProductShopHistoryVO.class, qOrder.createTime, qOrderProduct.name,qOrderProduct.category, qOrderProduct.brand, qOrderProduct.spec, qOrderProduct.unit, qOrderProduct.quantity))
                .from(qOrderProduct)
                .leftJoin(qOrder).on(qOrderProduct.order.id.eq(qOrder.id))
                .where(qOrder.shopId.eq(pageVO.getShopId()))
                .orderBy(qOrderProduct.id.desc());
        long totalCount = query.fetchCount();
        return Wrapper.success(new PageData<>(totalCount, query.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset()).fetch()));
    }

    /**
     * 售后能力 - 查询退货换货商品列表
     *
     * @param headers HttpHeaders信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<OrderAfterSalePageQueryVO>> pageAfterSaleOrders(HttpHeaders headers, OrderAfterSalePageVO pageVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);

        //Step 1: 参数判断
        OrderTypeEnum orderType = OrderTypeEnum.parse(pageVO.getOrderType());
        if(orderType == null) {
            return Wrapper.fail(ResponseCode.ORDER_TYPE_DOES_NOT_EXIST);
        }

        //Step 2: 规则
        // 2-1. 查询采购订单中选择的供应会员的订单数据，根据选择的售后订单类型进行筛选，只显示已收到第一批货之后的订单且当前订单外部状态不是待确认支付结果
        // 2-2. 如果订单类型为现货采购、询价采购、集采、积分兑换、渠道直采、渠道现货、渠道积分兑换，
        //      查询交易流程规则配置中流程类型为售后换货流程的工作流
        // 2-3. 如果订单类型为采购询价合同、采购竞价合同、采购招标合同只允许选择合同编号相同的订单，
        //      查询采购流程规则配置的流程类型为售后换货流程的适用当前合同的工作流

        //Step 3: 在IMobileOrderCommonService中有个类似的接口，如这里修改了则要做相应的修改
        switch (orderType) {
            case SPOT_PURCHASING:
            case INQUIRY_TO_PURCHASE:
            case COLLECTIVE_PURCHASE:
            case CREDITS_EXCHANGE:
            case CHANNEL_STRAIGHT_MINING:
            case CHANNEL_SPOT:
            case CHANNEL_POINT_EXCHANGE:
                return pageAfterSaleOrdersByTradeProcess(loginUser.getMemberId(), loginUser.getMemberRoleId(), pageVO);
            case QUERY_PRICE_CONTRACT:
            case PRICE_COMPETITION_CONTRACT_PURCHASE:
            case PURCHASE_CONTRACT_BIDDING:
            case REQUISITION_TO_PURCHASE:
                return pageAfterSaleOrdersByPurchaseProcess(loginUser.getMemberId(), loginUser.getMemberRoleId(), pageVO);
            default:
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }
    }

    /**
     * 售后能力 - “代客售后” - 查询退货换货商品列表
     *
     * @param headers HttpHeaders信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<OrderAfterSalePageQueryVO>> pageAgentAfterSaleOrders(HttpHeaders headers, OrderAgentAfterSalePageVO pageVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);

        //Step 1: 参数判断
        OrderTypeEnum orderType = OrderTypeEnum.parse(pageVO.getOrderType());
        if(orderType == null) {
            return Wrapper.fail(ResponseCode.ORDER_TYPE_DOES_NOT_EXIST);
        }

        //Step 2: 规则
        // 2-1. 查询采购订单中选择的供应会员的订单数据，根据选择的售后订单类型进行筛选，只显示已收到第一批货之后的订单且当前订单外部状态不是待确认支付结果
        // 2-2. 如果订单类型为现货采购、询价采购、集采、积分兑换、渠道直采、渠道现货、渠道积分兑换，
        //      查询交易流程规则配置中流程类型为售后换货流程的工作流
        // 2-3. 如果订单类型为采购询价合同、采购竞价合同、采购招标合同只允许选择合同编号相同的订单，
        //      查询采购流程规则配置的流程类型为售后换货流程的适用当前合同的工作流

        //Step 3: 在IMobileOrderCommonService中有个类似的接口，如这里修改了则要做相应的修改
        switch (orderType) {
            case SPOT_PURCHASING:
            case INQUIRY_TO_PURCHASE:
            case COLLECTIVE_PURCHASE:
            case CREDITS_EXCHANGE:
            case CHANNEL_STRAIGHT_MINING:
            case CHANNEL_SPOT:
            case CHANNEL_POINT_EXCHANGE:
                return pageAgentAfterSaleOrdersByTradeProcess(loginUser.getMemberId(), loginUser.getMemberRoleId(), pageVO);
            case QUERY_PRICE_CONTRACT:
            case PRICE_COMPETITION_CONTRACT_PURCHASE:
            case PURCHASE_CONTRACT_BIDDING:
            case REQUISITION_TO_PURCHASE:
                return pageAgentAfterSaleOrdersByPurchaseProcess(loginUser.getMemberId(), loginUser.getMemberRoleId(), pageVO);
            default:
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }
    }

    /**
     * 售后能力 - 查询已经确认支付结果的支付记录列表
     *
     * @param headers HttpHeaders信息
     * @param idVO    接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderAfterSalePaymentDetailVO>> findAfterSaleOrderPayments(HttpHeaders headers, OrderIdVO idVO) {
        baseCacheService.needLoginFromBusinessPlatform(headers);
        return findAfterSaleOrderPayments(idVO);
    }

    /**
     * 售后能力 - 查询已经确认支付结果的支付记录列表
     *
     * @param idVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderAfterSalePaymentDetailVO>> findAfterSaleOrderPayments(OrderIdVO idVO) {
        QOrderPaymentDO qOrderPayment = QOrderPaymentDO.orderPaymentDO;
        return Wrapper.success(jpaQueryFactory.select(Projections.constructor(OrderAfterSalePaymentDetailVO.class, qOrderPayment.id, qOrderPayment.payTime, qOrderPayment.batchNo, qOrderPayment.payNode, qOrderPayment.payRate, qOrderPayment.payAmount, qOrderPayment.fundMode, qOrderPayment.payType, qOrderPayment.payChannel, qOrderPayment.tradeNo))
                .from(qOrderPayment)
                .where(qOrderPayment.order.id.eq(idVO.getOrderId()))
                .where(qOrderPayment.payAmount.gt(BigDecimal.ZERO))
                .where(qOrderPayment.outerStatus.eq(OrderOuterStatusEnum.ACCOMPLISHED.getCode())).fetch());
    }

    /**
     * 物流能力 - 分页查询“待发货”状态的订单列表
     *
     * @param headers HttpHeaders 信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<LogisticsOrderQueryVO>> pageLogisticsOrders(HttpHeaders headers, OrderLogisticsPageVO pageVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        QOrderDO qOrder = QOrderDO.orderDO;
        JPAQuery<LogisticsOrderQueryVO> query = jpaQueryFactory.select(Projections.constructor(LogisticsOrderQueryVO.class, qOrder.id, qOrder.orderNo, qOrder.submitTime, qOrder.digest, qOrder.buyerMemberId, qOrder.buyerRoleId, qOrder.buyerMemberName))
                .from(qOrder)
                .where(qOrder.vendorMemberId.eq(loginUser.getMemberId()).and(qOrder.vendorRoleId.eq(loginUser.getMemberRoleId())))
                .where(qOrder.outerStatus.eq(OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode()));

        //订单编号
        if(StringUtils.hasLength(pageVO.getOrderNo())) {
            query.where(qOrder.orderNo.like("%" + pageVO.getOrderNo().trim() + "%"));
        }

        //订单摘要
        if(StringUtils.hasLength(pageVO.getDigest())) {
            query.where(qOrder.digest.like("%" + pageVO.getDigest().trim() + "%"));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getStartDate())) {
            query.where(qOrder.submitTime.after(LocalDateTime.parse(pageVO.getStartDate().concat(" 00:00:00"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getEndDate())) {
            query.where(qOrder.submitTime.before(LocalDateTime.parse(pageVO.getEndDate().concat(" 23:59:59"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //Step 4: 倒序排序、分页、总数
        long totalCount = query.fetchCount();
        query.orderBy(qOrder.submitTime.desc());
        query.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());

        return Wrapper.success(new PageData<>(totalCount, query.fetch()));
    }

    /**
     * 物流能力 - 根据订单Id，分页查询订单商品列表
     *
     * @param headers HttpHeaders 信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<LogisticsOrderProductQueryVO>> pageLogisticsOrderProducts(HttpHeaders headers, OrderProductLogisticsPageVO pageVO) {
        baseCacheService.needLoginFromBusinessPlatform(headers);
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        JPAQuery<LogisticsOrderProductQueryVO> query = jpaQueryFactory.select(Projections.constructor(LogisticsOrderProductQueryVO.class, qOrderProduct.id, qOrderProduct.productId, qOrderProduct.name, qOrderProduct.category, qOrderProduct.brand, qOrderProduct.spec))
                .from(qOrderProduct)
                .where(qOrderProduct.order.id.eq(pageVO.getOrderId()));

        //商品名称
        if(StringUtils.hasLength(pageVO.getName())) {
            query.where(qOrderProduct.name.like("%" + pageVO.getName().trim() + "%"));
        }

        //商品品类
        if(StringUtils.hasLength(pageVO.getCategory())) {
            query.where(qOrderProduct.category.like("%" + pageVO.getCategory().trim() + "%"));
        }

        //商品品牌
        if(StringUtils.hasLength(pageVO.getBrand())) {
            query.where(qOrderProduct.category.like("%" + pageVO.getBrand().trim() + "%"));
        }

        //Step 4: 顺序排序、分页、总数
        long totalCount = query.fetchCount();
        query.orderBy(qOrderProduct.id.asc());
        query.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());

        return Wrapper.success(new PageData<>(totalCount, query.fetch()));
    }

    /**
     * 加工能力 - 分页查询加工订单列表
     *
     * @param headers HttpHeaders信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<OrderEnhancePageQueryVO>> pageEnhanceOrders(HttpHeaders headers, OrderEnhancePageVO pageVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        //Step 1: 根据会员等级类型，校验订单类型参数
        //Step 1-1 : 会员类型：企业会员+个人会员，角色类型：服务提供者，数据来源于销售订单管理，取外部状态为已确认的订单且订单类型为现货采购、询价采购、需求采购、集采。
        //Step 1-2 : 会员类型：渠道企业会员+渠道个人会员，角色类型：服务提供者，数据来源于销售订单管理，取外部状态为已确认的订单且订单类型为渠道直采、渠道现货。
        if(!loginUser.getMemberRoleType().equals(RoleTypeEnum.SERVICE_PROVIDER.getCode())) {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }

        List<Integer> orderTypes = Stream.of(OrderTypeEnum.INQUIRY_TO_PURCHASE.getCode(), OrderTypeEnum.NEED_TO_PURCHASE.getCode(), OrderTypeEnum.SPOT_PURCHASING.getCode(), OrderTypeEnum.COLLECTIVE_PURCHASE.getCode()).collect(Collectors.toList());
        if(NumberUtil.notNullOrZero(pageVO.getOrderType())) {
            if(loginUser.getMemberLevelType().equals(MemberLevelTypeEnum.MERCHANT.getCode())) {
                orderTypes = Stream.of(OrderTypeEnum.INQUIRY_TO_PURCHASE.getCode(), OrderTypeEnum.NEED_TO_PURCHASE.getCode(), OrderTypeEnum.SPOT_PURCHASING.getCode(), OrderTypeEnum.COLLECTIVE_PURCHASE.getCode()).collect(Collectors.toList());
            }

            if(loginUser.getMemberLevelType().equals(MemberLevelTypeEnum.CHANNEL.getCode())) {
                orderTypes = Stream.of(OrderTypeEnum.CHANNEL_STRAIGHT_MINING.getCode(), OrderTypeEnum.CHANNEL_SPOT.getCode(), OrderTypeEnum.SPOT_PURCHASING.getCode(), OrderTypeEnum.COLLECTIVE_PURCHASE.getCode()).collect(Collectors.toList());
            }

            if(!orderTypes.contains(pageVO.getOrderType())) {
                return Wrapper.fail(ResponseCode.ORDER_TYPE_DOES_NOT_EXIST);
            }
        }

        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderTradeProcessDO qOrderTradeProcess = QOrderTradeProcessDO.orderTradeProcessDO;
        QOrderTradeProcessProductDO qOrderTradeProcessProduct = QOrderTradeProcessProductDO.orderTradeProcessProductDO;

        //Step 2: 定义总数查询关系
        JPAQuery<Long> countQuery = jpaQueryFactory.selectDistinct(qOrder.id).from(qOrder)
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderTradeProcess).on(qOrder.shopId.eq(qOrderTradeProcess.shopId).and(qOrder.vendorMemberId.eq(qOrderTradeProcess.memberId)).and(qOrder.vendorRoleId.eq(qOrderTradeProcess.roleId)))
                .leftJoin(qOrderTradeProcessProduct).on(qOrderTradeProcess.id.eq(qOrderTradeProcessProduct.process.id))
                .where(qOrder.vendorMemberId.eq(loginUser.getMemberId()).and(qOrder.vendorRoleId.eq(loginUser.getMemberRoleId())));

        //Step 2: 固定的查询条件
        //订单状态：外部状态为“已确认”
        List<Integer> notInOuterStatus = Stream.of(OrderOuterStatusEnum.TO_SUBMIT.getCode(), OrderOuterStatusEnum.TO_CONFIRM.getCode(), OrderOuterStatusEnum.NOT_ACCEPT.getCode(), OrderOuterStatusEnum.TO_ARCHIVE.getCode(), OrderOuterStatusEnum.ACCOMPLISHED.getCode(), OrderOuterStatusEnum.CANCELLED.getCode(), OrderOuterStatusEnum.TERMINATED.getCode()).collect(Collectors.toList());
        countQuery.where(qOrder.outerStatus.notIn(notInOuterStatus));

        //Step 3: 动态的查询条件
        //合同编号
        if(StringUtils.hasLength(pageVO.getOrderNo())) {
            countQuery.where(qOrder.orderNo.like("%" + pageVO.getOrderNo().trim() + "%"));
        }

        //订单摘要
        if(StringUtils.hasLength(pageVO.getDigest())) {
            countQuery.where(qOrder.digest.like("%" + pageVO.getDigest().trim() + "%"));
        }

        //采购会员名称
        if(StringUtils.hasLength(pageVO.getBuyerMemberName())) {
            countQuery.where(qOrder.buyerMemberName.like("%" + pageVO.getBuyerMemberName().trim() + "%"));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getStartDate())) {
            countQuery.where(qOrder.createTime.after(LocalDateTime.parse(pageVO.getStartDate().concat(" 00:00:00"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getEndDate())) {
            countQuery.where(qOrder.createTime.before(LocalDateTime.parse(pageVO.getEndDate().concat(" 23:59:59"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //订单类型
        if(NumberUtil.notNullOrZero(pageVO.getOrderType())) {
            countQuery.where(qOrder.orderType.eq(pageVO.getOrderType()));
        } else {
            countQuery.where(qOrder.orderType.in(orderTypes));
        }

        //Step 4: 共用的查询条件（字表的查询条件）
        //流程类型
        countQuery.where(qOrderTradeProcess.processType.eq(OrderTradeProcessTypeEnum.PRODUCTION.getCode()));
        //流程规则配置
        countQuery.where(qOrderTradeProcess.allProducts.isTrue().or(qOrderTradeProcessProduct.productId.eq(qOrderProduct.productId).and(qOrderTradeProcessProduct.skuId.eq(qOrderProduct.skuId))));

        //Step 5: 倒序排序、分页、总数
        long totalCount = countQuery.fetchCount();
        countQuery.orderBy(qOrder.id.desc());
        countQuery.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());

        //Step 6: 定义关联关系，OrderDO表必须要有distinct()
        JPAQuery<?> query = jpaQueryFactory.from(qOrder).distinct()
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderTradeProcess).on(qOrder.shopId.eq(qOrderTradeProcess.shopId).and(qOrder.vendorMemberId.eq(qOrderTradeProcess.memberId)).and(qOrder.vendorRoleId.eq(qOrderTradeProcess.roleId)))
                .leftJoin(qOrderTradeProcessProduct).on(qOrderTradeProcess.id.eq(qOrderTradeProcessProduct.process.id))
                .where(qOrder.id.in(countQuery.fetch()));

        //Step 7: 共有的查询条件
        //流程类型
        query.where(qOrderTradeProcess.processType.eq(OrderTradeProcessTypeEnum.PRODUCTION.getCode()));
        //流程规则配置
        query.where(qOrderTradeProcess.allProducts.isTrue().or(qOrderTradeProcessProduct.productId.eq(qOrderProduct.productId).and(qOrderTradeProcessProduct.skuId.eq(qOrderProduct.skuId))));

        //Step 8: 使用transform()对结果进行聚合统计，并通过Projections.Constructor到VO对象
        Map<Long, OrderEnhancePageQueryVO> transform = query.transform(GroupBy.groupBy(qOrder.id).as(
                Projections.constructor(OrderEnhancePageQueryVO.class, qOrder.id, qOrder.orderNo, qOrder.digest, qOrder.buyerMemberId, qOrder.buyerRoleId, qOrder.buyerMemberName, qOrder.orderType, qOrder.submitTime, qOrder.outerStatus,
                        GroupBy.list(Projections.constructor(OrderEnhanceProductDetailVO.class,
                                qOrderTradeProcess.processKey,
                                qOrderProduct.id,
                                qOrderProduct.name,
                                qOrderProduct.category,
                                qOrderProduct.brand,
                                qOrderProduct.spec,
                                qOrderProduct.unit,
                                qOrderProduct.quantity,
                                qOrderProduct.enhanceCount
                        )))));

        return Wrapper.success(new PageData<>(totalCount, new ArrayList<>(transform.values())));
    }

    /**
     * 支付能力 - 查询会员支付渠道列表
     *
     * @param headers   HttpHeaders信息
     * @param payTypeVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderPayChannelDetailVO>> findMemberPayChannels(HttpHeaders headers, OrderMemberPayTypeVO payTypeVO) {
        baseCacheService.checkUserFromCache(headers);
        List<PlatformPayTypeBO> platformPayTypes = baseOrderProcessService.findPlatformMemberPayment(payTypeVO.getMemberId(), payTypeVO.getRoleId());
        return Wrapper.success(platformPayTypes.stream().filter(platformPayType -> platformPayType.getPayType().equals(payTypeVO.getPayType())).flatMap(platformPayType -> platformPayType.getChannels().stream()).map(payChannel -> new OrderPayChannelDetailVO(payChannel.getPayChannel(), OrderPayChannelEnum.getNameByCode(payChannel.getPayChannel()))).sorted(Comparator.comparingInt(OrderPayChannelDetailVO::getPayChannel)).collect(Collectors.toList()));
    }

    /**
     * 结算能力 - 开票管理 - 根据订单号查看订单详情
     * @param headers HttpHeaders信息
     * @param orderVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<VendorOrderDetailVO> findSettleOrderDetailByOrderNo(HttpHeaders headers, OrderNoVO orderVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        OrderDO order = orderRepository.findFirstByOrderNo(orderVO.getOrderNo());
        if (order == null) {
            return Wrapper.fail(ResponseCode.ORDER_DOES_NOT_EXIST);
        }
        if (!order.getVendorMemberId().equals(loginUser.getMemberId()) || !order.getVendorRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.ORDER_WRONG_ROLE);
        }

        return baseOrderService.getVendorOrderDetail(order);
    }

    /**
     * 商品能力 - 上架指引查询商品是否配置了交易流程
     *
     * @param headers   HttpHeaders信息
     * @param processVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderProductProcessQueryVO>> findProductProcess(HttpHeaders headers, OrderProductProcessVO processVO) {
        UserLoginCacheDTO loginUser = baseCacheService.needLoginFromBusinessPlatform(headers);
        return baseOrderProcessService.findProductProcess(loginUser.getMemberId(), loginUser.getMemberRoleId(), processVO.getShopIds(), processVO.getShopType(), processVO.getProducts());
    }

    /**
     * 根据交易流程规则配置查询售后订单
     * @param buyerMemberId 采购会员Id（当前会员Id）
     * @param buyerRoleId   采购会员角色Id（当前会员角色Id）
     * @param pageVO         接口参数
     * @return               查询结果
     */
    private Wrapper<PageData<OrderAfterSalePageQueryVO>> pageAfterSaleOrdersByTradeProcess(Long buyerMemberId, Long buyerRoleId, OrderAfterSalePageVO pageVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderMaterialDO qOrderMaterial = QOrderMaterialDO.orderMaterialDO;
        QOrderContractDO qOrderContract = QOrderContractDO.orderContractDO;
        QOrderTradeProcessDO qOrderTradeProcess = QOrderTradeProcessDO.orderTradeProcessDO;
        QOrderTradeProcessProductDO qOrderTradeProcessProduct = QOrderTradeProcessProductDO.orderTradeProcessProductDO;

        //由于QueryDsl的关联查询中，无法对主表进行分页，所以要分开查询
        //Step 1: 构造总数查询，所有查询条件的表都必须关联定义
        JPAQuery<Long> countQuery = jpaQueryFactory.selectDistinct(qOrder.id).from(qOrder)
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderTradeProcess).on(qOrder.shopId.eq(qOrderTradeProcess.shopId).and(qOrder.vendorMemberId.eq(qOrderTradeProcess.memberId)).and(qOrder.vendorRoleId.eq(qOrderTradeProcess.roleId)))
                .leftJoin(qOrderTradeProcessProduct).on(qOrderTradeProcess.id.eq(qOrderTradeProcessProduct.process.id))
                .where(qOrder.orderType.eq(pageVO.getOrderType()));

        //Step 2: 固定的查询条件
        //采购会员、供应会员
        countQuery.where(qOrder.buyerMemberId.eq(buyerMemberId).and(qOrder.buyerRoleId.eq(buyerRoleId)).and(qOrder.vendorMemberId.eq(pageVO.getVendorMemberId())).and(qOrder.vendorRoleId.eq(pageVO.getVendorRoleId())));

        //订单状态：
        //换货：只显示已收到第一批货之后的订单且当前订单外部状态不是待确认支付结果
        //退货：只显示已发过第一批货之后、或已经支付成功过一次的订单且当前订单外部状态不是待确认支付结果，且订单状态不是已中止
        //维修：只显示已收到第一批货之后的订单
        if(pageVO.getAfterSalesType().equals(OrderTradeProcessTypeEnum.AFTER_SALES_EXCHANGES.getCode())) {
            countQuery.where(qOrder.hasReceived.isTrue().and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode())));
        } else if(pageVO.getAfterSalesType().equals(OrderTradeProcessTypeEnum.AFTER_SALES_RETURNS.getCode())) {
            countQuery.where(qOrder.hasDelivered.isTrue().or(qOrder.hasPaid.isTrue()));
            countQuery.where(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode()).and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TERMINATED.getCode())));
        } else {
            countQuery.where(qOrder.hasReceived.isTrue());
        }

        //Step 3: 动态的查询条件
        //合同编号
        if(StringUtils.hasLength(pageVO.getOrderNo())) {
            countQuery.where(qOrder.orderNo.like("%" + pageVO.getOrderNo().trim() + "%"));
        }

        //订单摘要
        if(StringUtils.hasLength(pageVO.getDigest())) {
            countQuery.where(qOrder.digest.like("%" + pageVO.getDigest().trim() + "%"));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getStartDate())) {
            countQuery.where(qOrder.createTime.after(LocalDateTime.parse(pageVO.getStartDate().concat(" 00:00:00"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getEndDate())) {
            countQuery.where(qOrder.createTime.before(LocalDateTime.parse(pageVO.getEndDate().concat(" 23:59:59"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //Step 4: 总数查询和分页查询共用的查询条件（即关联表的查询条件），必须在列表查询中再次定义
        //只可选择已退货数量小于订单数量的订单商品
        countQuery.where(qOrderProduct.returnCount.lt(qOrderProduct.quantity));
        //流程类型、状态
        countQuery.where(qOrderTradeProcess.processType.eq(pageVO.getAfterSalesType()).and(qOrderTradeProcess.status.eq(EnableDisableStatus.ENABLE.getCode())));
        //流程规则配置
        countQuery.where(qOrderTradeProcess.allProducts.isTrue().or(qOrderTradeProcessProduct.productId.eq(qOrderProduct.productId).and(qOrderTradeProcessProduct.skuId.eq(qOrderProduct.skuId))));

        //Step 5: 先查总数，然后倒序排序、分页
        long totalCount = countQuery.fetchCount();
        countQuery.orderBy(qOrder.id.desc());
        countQuery.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());

        //Step 6: 定义关联关系，OrderDO表必须要有distinct()，这里对主表（订单表的查询条件不需要再定义了，要用 in 查询）
        JPAQuery<?> query = jpaQueryFactory.from(qOrder).distinct()
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderMaterial).on(qOrderProduct.id.eq(qOrderMaterial.orderProduct.id))
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .leftJoin(qOrderTradeProcess).on(qOrder.shopId.eq(qOrderTradeProcess.shopId).and(qOrder.vendorMemberId.eq(qOrderTradeProcess.memberId)).and(qOrder.vendorRoleId.eq(qOrderTradeProcess.roleId)))
                .leftJoin(qOrderTradeProcessProduct).on(qOrderTradeProcess.id.eq(qOrderTradeProcessProduct.process.id))
                .where(qOrder.id.in(countQuery.fetch()));

        //共用的查询条件也必须定义
        //只可选择已退货数量小于订单数量的订单商品
        query.where(qOrderProduct.returnCount.lt(qOrderProduct.quantity));
        //流程类型、状态
        query.where(qOrderTradeProcess.processType.eq(pageVO.getAfterSalesType()).and(qOrderTradeProcess.status.eq(EnableDisableStatus.ENABLE.getCode())));
        //流程规则配置
        query.where(qOrderTradeProcess.allProducts.isTrue().or(qOrderTradeProcessProduct.productId.eq(qOrderProduct.productId).and(qOrderTradeProcessProduct.skuId.eq(qOrderProduct.skuId))));

        //Step 7: 使用transform()对结果进行聚合统计，并通过Projections.Constructor到VO对象
        Map<Long, OrderAfterSalePageQueryVO> transform = query.transform(GroupBy.groupBy(qOrder.id).as(
                Projections.constructor(OrderAfterSalePageQueryVO.class, qOrder.shopId, qOrder.id, qOrder.orderNo, qOrder.digest, qOrder.vendorMemberId, qOrder.vendorRoleId, qOrder.vendorMemberName, qOrder.orderType, qOrder.createTime, qOrder.outerStatus, qOrderContract.contractId, qOrderContract.contractNo,
                        GroupBy.list(Projections.constructor(OrderAfterSaleProductDetailVO.class,
                                qOrderProduct.id,
                                qOrder.orderType,
                                qOrderTradeProcess.processKey,
                                qOrderProduct.skuId,
                                qOrderProduct.productNo,
                                qOrderProduct.logo,
                                qOrderProduct.name,
                                qOrderProduct.category,
                                qOrderProduct.brand,
                                qOrderProduct.unit,
                                qOrderProduct.spec,
                                qOrderProduct.quantity,
                                qOrderProduct.refPrice,
                                qOrderProduct.amount,
                                qOrderProduct.paidAmount,
                                qOrderProduct.exchangeCount,
                                qOrderProduct.returnCount,
                                qOrderProduct.maintainCount,
                                qOrderProduct.returnAmount,
                                qOrderProduct.tax,
                                qOrderProduct.taxRate,
                                qOrderProduct.priceType,
                                qOrderMaterial.skuId,
                                qOrderMaterial.productNo,
                                qOrderMaterial.name,
                                qOrderMaterial.category,
                                qOrderMaterial.brand,
                                qOrderMaterial.spec
                        )))));

        List<OrderAfterSalePageQueryVO> queryResult = new ArrayList<>(transform.values());
        //Step 8: 查询店铺Logo
        findShopLogos(queryResult);

        return Wrapper.success(new PageData<>(totalCount, queryResult));
    }

    /**
     * 根据采购流程规则配置查询售后订单
     * @param buyerMemberId 采购会员Id（当前会员Id）
     * @param buyerRoleId   采购会员角色Id（当前会员角色Id）
     * @param pageVO         接口参数
     * @return               查询结果
     */
    private Wrapper<PageData<OrderAfterSalePageQueryVO>> pageAfterSaleOrdersByPurchaseProcess(Long buyerMemberId, Long buyerRoleId, OrderAfterSalePageVO pageVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderMaterialDO qOrderMaterial = QOrderMaterialDO.orderMaterialDO;
        QOrderContractDO qOrderContract = QOrderContractDO.orderContractDO;
        QOrderPurchaseProcessDO qOrderPurchaseProcess = QOrderPurchaseProcessDO.orderPurchaseProcessDO;
        QOrderPurchaseProcessContractDO qOrderPurchaseProcessContract = QOrderPurchaseProcessContractDO.orderPurchaseProcessContractDO;

        //Step 1: 定义总数查询
        JPAQuery<Long> countQuery = jpaQueryFactory.selectDistinct(qOrder.id).from(qOrder)
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderMaterial).on(qOrderProduct.id.eq(qOrderMaterial.orderProduct.id))
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .leftJoin(qOrderPurchaseProcess).on(qOrder.buyerMemberId.eq(qOrderPurchaseProcess.memberId).and(qOrder.buyerRoleId.eq(qOrderPurchaseProcess.roleId)))
                .leftJoin(qOrderPurchaseProcessContract).on(qOrderPurchaseProcess.id.eq(qOrderPurchaseProcessContract.process.id))
                .where(qOrder.orderType.eq(pageVO.getOrderType()));

        //Step 2: 固定的查询条件
        //采购会员、供应会员与订单类型
        countQuery.where(qOrder.buyerMemberId.eq(buyerMemberId).and(qOrder.buyerRoleId.eq(buyerRoleId)).and(qOrder.vendorMemberId.eq(pageVO.getVendorMemberId())).and(qOrder.vendorRoleId.eq(pageVO.getVendorRoleId())));

        //订单状态：
        //换货：只显示已收到第一批货之后的订单且当前订单外部状态不是待确认支付结果
        //退货：只显示已发过第一批货之后、或已经支付成功过一次的订单且当前订单外部状态不是待确认支付结果，且订单状态不是已中止
        //维修：只显示已收到第一批货之后的订单
        if(pageVO.getAfterSalesType().equals(OrderTradeProcessTypeEnum.AFTER_SALES_EXCHANGES.getCode())) {
            countQuery.where(qOrder.hasReceived.isTrue().and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode())));
        } else if(pageVO.getAfterSalesType().equals(OrderTradeProcessTypeEnum.AFTER_SALES_RETURNS.getCode())) {
            countQuery.where(qOrder.hasDelivered.isTrue().or(qOrder.hasPaid.isTrue()));
            countQuery.where(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode()).and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TERMINATED.getCode())));
        } else {
            countQuery.where(qOrder.hasReceived.isTrue());
        }

        //Step 3: 动态的查询条件
        //合同编号
        if(StringUtils.hasLength(pageVO.getOrderNo())) {
            countQuery.where(qOrder.orderNo.like("%" + pageVO.getOrderNo().trim() + "%"));
        }

        //订单摘要
        if(StringUtils.hasLength(pageVO.getDigest())) {
            countQuery.where(qOrder.digest.like("%" + pageVO.getDigest().trim() + "%"));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getStartDate())) {
            countQuery.where(qOrder.createTime.after(LocalDateTime.parse(pageVO.getStartDate().concat(" 00:00:00"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getEndDate())) {
            countQuery.where(qOrder.createTime.before(LocalDateTime.parse(pageVO.getEndDate().concat(" 23:59:59"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //Step 4: 共用的查询条件
        //只可选择已退货数量小于订单数量的订单商品
        countQuery.where(qOrderProduct.returnCount.lt(qOrderProduct.quantity));
        //流程类型、状态
        countQuery.where(qOrderPurchaseProcess.processType.eq(pageVO.getAfterSalesType()).and(qOrderPurchaseProcess.status.eq(EnableDisableStatus.ENABLE.getCode())));
        //流程规则配置
        countQuery.where(qOrderPurchaseProcess.allContracts.isTrue().or(qOrderPurchaseProcessContract.contractId.eq(qOrderContract.contractId)));

        //Step 5: 倒序排序、分页、总数
        long totalCount = countQuery.fetchCount();
        countQuery.orderBy(qOrder.id.desc());
        countQuery.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());

        //Step 6: 定义关联关系，OrderDO表必须要有distinct()
        //        这里订单Id用了in() 查询
        JPAQuery<?> query = jpaQueryFactory.from(qOrder).distinct()
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderMaterial).on(qOrderProduct.id.eq(qOrderMaterial.orderProduct.id))
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .leftJoin(qOrderPurchaseProcess).on(qOrder.buyerMemberId.eq(qOrderPurchaseProcess.memberId).and(qOrder.buyerRoleId.eq(qOrderPurchaseProcess.roleId)))
                .leftJoin(qOrderPurchaseProcessContract).on(qOrderPurchaseProcess.id.eq(qOrderPurchaseProcessContract.process.id))
                .where(qOrder.id.in(countQuery.fetch()));

        //Step 7: 共用的查询条件
        //只可选择已退货数量小于订单数量的订单商品
        query.where(qOrderProduct.returnCount.lt(qOrderProduct.quantity));
        //流程类型、状态
        query.where(qOrderPurchaseProcess.processType.eq(pageVO.getAfterSalesType()).and(qOrderPurchaseProcess.status.eq(EnableDisableStatus.ENABLE.getCode())));
        //流程规则配置
        query.where(qOrderPurchaseProcess.allContracts.isTrue().or(qOrderPurchaseProcessContract.contractId.eq(qOrderContract.contractId)));

        //Step 8: 使用transform()对结果进行聚合统计，并通过Projections.Constructor到VO对象
        Map<Long, OrderAfterSalePageQueryVO> transform = query.transform(GroupBy.groupBy(qOrder.id).as(
                Projections.constructor(OrderAfterSalePageQueryVO.class, qOrder.shopId, qOrder.id, qOrder.orderNo, qOrder.digest, qOrder.vendorMemberId, qOrder.vendorRoleId, qOrder.vendorMemberName, qOrder.orderType, qOrder.createTime, qOrder.outerStatus, qOrderContract.contractId, qOrderContract.contractNo,
                        GroupBy.list(Projections.constructor(OrderAfterSaleProductDetailVO.class,
                                qOrderProduct.id,
                                qOrder.orderType,
                                qOrderPurchaseProcess.processKey,
                                qOrderProduct.skuId,
                                qOrderProduct.productNo,
                                qOrderProduct.logo,
                                qOrderProduct.name,
                                qOrderProduct.category,
                                qOrderProduct.brand,
                                qOrderProduct.unit,
                                qOrderProduct.spec,
                                qOrderProduct.quantity,
                                qOrderProduct.refPrice,
                                qOrderProduct.amount,
                                qOrderProduct.paidAmount,
                                qOrderProduct.exchangeCount,
                                qOrderProduct.returnCount,
                                qOrderProduct.maintainCount,
                                qOrderProduct.returnAmount,
                                qOrderProduct.tax,
                                qOrderProduct.taxRate,
                                qOrderProduct.priceType,
                                qOrderMaterial.skuId,
                                qOrderMaterial.productNo,
                                qOrderMaterial.name,
                                qOrderMaterial.category,
                                qOrderMaterial.brand,
                                qOrderMaterial.spec
                        )))));

        List<OrderAfterSalePageQueryVO> queryResult = new ArrayList<>(transform.values());

        //Step 9: 查询店铺Logo
        findShopLogos(queryResult);

        return Wrapper.success(new PageData<>(totalCount, queryResult));
    }

    /**
     * “代客售后” - 根据交易流程规则配置查询售后订单
     * @param vendorMemberId 供应会员Id（当前会员Id）
     * @param vendorRoleId   供应会员角色Id（当前会员角色Id）
     * @param pageVO         接口参数
     * @return               查询结果
     */
    private Wrapper<PageData<OrderAfterSalePageQueryVO>> pageAgentAfterSaleOrdersByTradeProcess(Long vendorMemberId, Long vendorRoleId, OrderAgentAfterSalePageVO pageVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderMaterialDO qOrderMaterial = QOrderMaterialDO.orderMaterialDO;
        QOrderContractDO qOrderContract = QOrderContractDO.orderContractDO;
        QOrderTradeProcessDO qOrderTradeProcess = QOrderTradeProcessDO.orderTradeProcessDO;
        QOrderTradeProcessProductDO qOrderTradeProcessProduct = QOrderTradeProcessProductDO.orderTradeProcessProductDO;

        //Step 1: 定义总数查询
        JPAQuery<Long> countQuery = jpaQueryFactory.selectDistinct(qOrder.id).from(qOrder)
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderMaterial).on(qOrderProduct.id.eq(qOrderMaterial.orderProduct.id))
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .leftJoin(qOrderTradeProcess).on(qOrder.shopId.eq(qOrderTradeProcess.shopId).and(qOrder.vendorMemberId.eq(qOrderTradeProcess.memberId)).and(qOrder.vendorRoleId.eq(qOrderTradeProcess.roleId)))
                .leftJoin(qOrderTradeProcessProduct).on(qOrderTradeProcess.id.eq(qOrderTradeProcessProduct.process.id))
                .where(qOrder.orderType.eq(pageVO.getOrderType()));

        //Step 2: 固定的查询条件
        //采购会员、供应会员
        countQuery.where(qOrder.buyerMemberId.eq(pageVO.getBuyerMemberId()).and(qOrder.buyerRoleId.eq(pageVO.getBuyerRoleId())).and(qOrder.vendorMemberId.eq(vendorMemberId)).and(qOrder.vendorRoleId.eq(vendorRoleId)));

        //订单状态：
        //换货：只显示已收到第一批货之后的订单且当前订单外部状态不是待确认支付结果,排除外部状态是待支付
        //退货：只显示已发过第一批货之后、或已经支付成功过一次的订单且当前订单外部状态不是待确认支付结果，且订单状态不是已中止, 排除待支付
        //维修：只显示已收到第一批货之后的订单,排除待发货
        if(pageVO.getAfterSalesType().equals(OrderTradeProcessTypeEnum.AFTER_SALES_EXCHANGES.getCode())) {
            countQuery.where(qOrder.hasReceived.isTrue()
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode()))
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_PAY.getCode())));
        } else if(pageVO.getAfterSalesType().equals(OrderTradeProcessTypeEnum.AFTER_SALES_RETURNS.getCode())) {
            countQuery.where(qOrder.hasDelivered.isTrue().or(qOrder.hasPaid.isTrue()));
            countQuery.where(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode())
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TERMINATED.getCode()))
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode()))
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_PAY.getCode())));
        } else {
            countQuery.where(qOrder.hasReceived.isTrue());
            countQuery.where(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode())
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_PAY.getCode())));

        }

        //Step 3: 动态的查询条件
        //合同编号
        if(StringUtils.hasLength(pageVO.getOrderNo())) {
            countQuery.where(qOrder.orderNo.like("%" + pageVO.getOrderNo().trim() + "%"));
        }

        //订单摘要
        if(StringUtils.hasLength(pageVO.getDigest())) {
            countQuery.where(qOrder.digest.like("%" + pageVO.getDigest().trim() + "%"));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getStartDate())) {
            countQuery.where(qOrder.createTime.after(LocalDateTime.parse(pageVO.getStartDate().concat(" 00:00:00"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getEndDate())) {
            countQuery.where(qOrder.createTime.before(LocalDateTime.parse(pageVO.getEndDate().concat(" 23:59:59"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //Step 4: 共用的查询条件（字表的查询条件）
        //只可选择已退货数量小于订单数量的订单商品
        countQuery.where(qOrderProduct.returnCount.lt(qOrderProduct.quantity));
        //流程类型、状态
        countQuery.where(qOrderTradeProcess.processType.eq(pageVO.getAfterSalesType()).and(qOrderTradeProcess.status.eq(EnableDisableStatus.ENABLE.getCode())));
        //流程规则配置
        countQuery.where(qOrderTradeProcess.allProducts.isTrue().or(qOrderTradeProcessProduct.productId.eq(qOrderProduct.productId).and(qOrderTradeProcessProduct.skuId.eq(qOrderProduct.skuId))));

        //Step 5: 总数、倒序排序、分页
        long totalCount = countQuery.fetchCount();
        countQuery.orderBy(qOrder.id.desc());
        countQuery.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());

        //Step 6: 定义关联关系，OrderDO表必须要有distinct()
        JPAQuery<?> query = jpaQueryFactory.from(qOrder).distinct()
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderMaterial).on(qOrderProduct.id.eq(qOrderMaterial.orderProduct.id))
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .leftJoin(qOrderTradeProcess).on(qOrder.shopId.eq(qOrderTradeProcess.shopId).and(qOrder.vendorMemberId.eq(qOrderTradeProcess.memberId)).and(qOrder.vendorRoleId.eq(qOrderTradeProcess.roleId)))
                .leftJoin(qOrderTradeProcessProduct).on(qOrderTradeProcess.id.eq(qOrderTradeProcessProduct.process.id))
                .where(qOrder.id.in(countQuery.fetch()));

        //Step 7: 共用的查询条件（字表的查询条件）
        //只可选择已退货数量小于订单数量的订单商品
        query.where(qOrderProduct.returnCount.lt(qOrderProduct.quantity));
        //流程类型、状态
        query.where(qOrderTradeProcess.processType.eq(pageVO.getAfterSalesType()).and(qOrderTradeProcess.status.eq(EnableDisableStatus.ENABLE.getCode())));
        //流程规则配置
        query.where(qOrderTradeProcess.allProducts.isTrue().or(qOrderTradeProcessProduct.productId.eq(qOrderProduct.productId).and(qOrderTradeProcessProduct.skuId.eq(qOrderProduct.skuId))));

        //Step 8: 使用transform()对结果进行聚合统计，并通过Projections.Constructor到VO对象
        Map<Long, OrderAfterSalePageQueryVO> transform = query.transform(GroupBy.groupBy(qOrder.id).as(
                Projections.constructor(OrderAfterSalePageQueryVO.class, qOrder.shopId, qOrder.id, qOrder.orderNo, qOrder.digest, qOrder.vendorMemberId, qOrder.vendorRoleId, qOrder.vendorMemberName, qOrder.orderType, qOrder.createTime, qOrder.outerStatus, qOrderContract.contractId, qOrderContract.contractNo,
                        GroupBy.list(Projections.constructor(OrderAfterSaleProductDetailVO.class,
                                qOrderProduct.id,
                                qOrder.orderType,
                                qOrderTradeProcess.processKey,
                                qOrderProduct.skuId,
                                qOrderProduct.productNo,
                                qOrderProduct.logo,
                                qOrderProduct.name,
                                qOrderProduct.category,
                                qOrderProduct.brand,
                                qOrderProduct.unit,
                                qOrderProduct.spec,
                                qOrderProduct.quantity,
                                qOrderProduct.refPrice,
                                qOrderProduct.amount,
                                qOrderProduct.paidAmount,
                                qOrderProduct.exchangeCount,
                                qOrderProduct.returnCount,
                                qOrderProduct.maintainCount,
                                qOrderProduct.returnAmount,
                                qOrderProduct.tax,
                                qOrderProduct.taxRate,
                                qOrderProduct.priceType,
                                qOrderMaterial.skuId,
                                qOrderMaterial.productNo,
                                qOrderMaterial.name,
                                qOrderMaterial.category,
                                qOrderMaterial.brand,
                                qOrderMaterial.spec
                        )))));

        List<OrderAfterSalePageQueryVO> queryResult = new ArrayList<>(transform.values());
        findShopLogos(queryResult);

        return Wrapper.success(new PageData<>(totalCount, queryResult));
    }

    /**
     * “代客售后” - 根据采购流程规则配置查询售后订单
     * @param vendorMemberId 供应会员Id（当前会员Id）
     * @param vendorRoleId   供应会员角色Id（当前会员角色Id）
     * @param pageVO         接口参数
     * @return               查询结果
     */
    private Wrapper<PageData<OrderAfterSalePageQueryVO>> pageAgentAfterSaleOrdersByPurchaseProcess(Long vendorMemberId, Long vendorRoleId, OrderAgentAfterSalePageVO pageVO) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderMaterialDO qOrderMaterial = QOrderMaterialDO.orderMaterialDO;
        QOrderContractDO qOrderContract = QOrderContractDO.orderContractDO;
        QOrderPurchaseProcessDO qOrderPurchaseProcess = QOrderPurchaseProcessDO.orderPurchaseProcessDO;
        QOrderPurchaseProcessContractDO qOrderPurchaseProcessContract = QOrderPurchaseProcessContractDO.orderPurchaseProcessContractDO;

        //Step 1: 定义总数查询
        JPAQuery<Long> countQuery = jpaQueryFactory.selectDistinct(qOrder.id).from(qOrder)
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderMaterial).on(qOrderProduct.id.eq(qOrderMaterial.orderProduct.id))
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .leftJoin(qOrderPurchaseProcess).on(qOrder.buyerMemberId.eq(qOrderPurchaseProcess.memberId).and(qOrder.buyerRoleId.eq(qOrderPurchaseProcess.roleId)))
                .leftJoin(qOrderPurchaseProcessContract).on(qOrderPurchaseProcess.id.eq(qOrderPurchaseProcessContract.process.id))
                .where(qOrder.orderType.eq(pageVO.getOrderType()));

        //Step 2: 固定的查询条件
        //采购会员、供应会员与订单类型
        countQuery.where(qOrder.buyerMemberId.eq(pageVO.getBuyerMemberId()).and(qOrder.buyerRoleId.eq(pageVO.getBuyerRoleId())).and(qOrder.vendorMemberId.eq(vendorMemberId)).and(qOrder.vendorRoleId.eq(vendorRoleId)));

        //订单状态：
        //换货：只显示已收到第一批货之后的订单且当前订单外部状态不是待确认支付结果，排除外部状态待支付
        //退货：只显示已发过第一批货之后、或已经支付成功过一次的订单且当前订单外部状态不是待确认支付结果，且订单状态不是已中止
        //维修：只显示已收到第一批货之后的订单
        if(pageVO.getAfterSalesType().equals(OrderTradeProcessTypeEnum.AFTER_SALES_EXCHANGES.getCode())) {
            countQuery.where(qOrder.hasReceived.isTrue()
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode()))
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_PAY.getCode())));
        } else if(pageVO.getAfterSalesType().equals(OrderTradeProcessTypeEnum.AFTER_SALES_RETURNS.getCode())) {
            countQuery.where(qOrder.hasDelivered.isTrue().or(qOrder.hasPaid.isTrue()));
            countQuery.where(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_PAYMENT.getCode())
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TERMINATED.getCode()))
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode()))
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_PAY.getCode())));
        } else {
            countQuery.where(qOrder.hasReceived.isTrue());
            countQuery.where(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode())
                    .and(qOrder.outerStatus.ne(OrderOuterStatusEnum.TO_PAY.getCode())));

        }

        //Step 3: 动态的查询条件
        //合同编号
        if(StringUtils.hasLength(pageVO.getOrderNo())) {
            countQuery.where(qOrder.orderNo.like("%" + pageVO.getOrderNo().trim() + "%"));
        }

        //订单摘要
        if(StringUtils.hasLength(pageVO.getDigest())) {
            countQuery.where(qOrder.digest.like("%" + pageVO.getDigest().trim() + "%"));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getStartDate())) {
            countQuery.where(qOrder.createTime.after(LocalDateTime.parse(pageVO.getStartDate().concat(" 00:00:00"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //订单起始时间
        if(StringUtils.hasLength(pageVO.getEndDate())) {
            countQuery.where(qOrder.createTime.before(LocalDateTime.parse(pageVO.getEndDate().concat(" 23:59:59"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //Step 4: 共有的查询条件（字表的查询条件）
        //只可选择已退货数量小于订单数量的订单商品
        countQuery.where(qOrderProduct.returnCount.lt(qOrderProduct.quantity));
        //流程类型、状态
        countQuery.where(qOrderPurchaseProcess.processType.eq(pageVO.getAfterSalesType()).and(qOrderPurchaseProcess.status.eq(EnableDisableStatus.ENABLE.getCode())));
        //流程规则配置
        countQuery.where(qOrderPurchaseProcess.allContracts.isTrue().or(qOrderPurchaseProcessContract.contractId.eq(qOrderContract.contractId)));

        //Step 5: 倒序排序、分页、总数
        long totalCount = countQuery.fetchCount();
        countQuery.orderBy(qOrder.id.desc());
        countQuery.limit(pageVO.getPageSize()).offset(pageVO.getCurrentOffset());

        //Step 6: 定义关联关系，OrderDO表必须要有distinct()
        JPAQuery<?> query = jpaQueryFactory.from(qOrder).distinct()
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderMaterial).on(qOrderProduct.id.eq(qOrderMaterial.orderProduct.id))
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .leftJoin(qOrderPurchaseProcess).on(qOrder.buyerMemberId.eq(qOrderPurchaseProcess.memberId).and(qOrder.buyerRoleId.eq(qOrderPurchaseProcess.roleId)))
                .leftJoin(qOrderPurchaseProcessContract).on(qOrderPurchaseProcess.id.eq(qOrderPurchaseProcessContract.process.id))
                .where(qOrder.id.in(countQuery.fetch()));

        //Step 7: 共有的查询条件
        //只可选择已退货数量小于订单数量的订单商品
        query.where(qOrderProduct.returnCount.lt(qOrderProduct.quantity));
        //流程类型、状态
        query.where(qOrderPurchaseProcess.processType.eq(pageVO.getAfterSalesType()).and(qOrderPurchaseProcess.status.eq(EnableDisableStatus.ENABLE.getCode())));
        //流程规则配置
        query.where(qOrderPurchaseProcess.allContracts.isTrue().or(qOrderPurchaseProcessContract.contractId.eq(qOrderContract.contractId)));

        //Step 8: 使用transform()对结果进行聚合统计，并通过Projections.Constructor到VO对象
        Map<Long, OrderAfterSalePageQueryVO> transform = query.transform(GroupBy.groupBy(qOrder.id).as(
                Projections.constructor(OrderAfterSalePageQueryVO.class, qOrder.shopId, qOrder.id, qOrder.orderNo, qOrder.digest, qOrder.vendorMemberId, qOrder.vendorRoleId, qOrder.vendorMemberName, qOrder.orderType, qOrder.createTime, qOrder.outerStatus, qOrderContract.contractId, qOrderContract.contractNo,
                        GroupBy.list(Projections.constructor(OrderAfterSaleProductDetailVO.class,
                                qOrderProduct.id,
                                qOrder.orderType,
                                qOrderPurchaseProcess.processKey,
                                qOrderProduct.skuId,
                                qOrderProduct.productNo,
                                qOrderProduct.logo,
                                qOrderProduct.name,
                                qOrderProduct.category,
                                qOrderProduct.brand,
                                qOrderProduct.unit,
                                qOrderProduct.spec,
                                qOrderProduct.quantity,
                                qOrderProduct.refPrice,
                                qOrderProduct.amount,
                                qOrderProduct.paidAmount,
                                qOrderProduct.exchangeCount,
                                qOrderProduct.returnCount,
                                qOrderProduct.maintainCount,
                                qOrderProduct.returnAmount,
                                qOrderProduct.tax,
                                qOrderProduct.taxRate,
                                qOrderProduct.priceType,
                                qOrderMaterial.skuId,
                                qOrderMaterial.productNo,
                                qOrderMaterial.name,
                                qOrderMaterial.category,
                                qOrderMaterial.brand,
                                qOrderMaterial.spec
                        )))));

        List<OrderAfterSalePageQueryVO> queryResult = new ArrayList<>(transform.values());
        findShopLogos(queryResult);

        return Wrapper.success(new PageData<>(totalCount, queryResult));
    }

    /**
     * 从店铺模板服务查询供应商店铺、自营商城Logo
     * @param queryResult 查询结果
     */
    private void findShopLogos(List<OrderAfterSalePageQueryVO> queryResult) {
        if(CollectionUtils.isEmpty(queryResult)) {
            return;
        }

        Map<Long, List<OrderAfterSalePageQueryVO>> map = queryResult.stream().collect(Collectors.groupingBy(OrderAfterSalePageQueryVO::getShopId));
        for (Map.Entry<Long, List<OrderAfterSalePageQueryVO>> entry : map.entrySet()) {
            Wrapper<List<VendorLogoDTO>> logoResult = platformTemplateFeignService.findVendorShopLogos(entry.getKey(), entry.getValue().stream().map(q -> new VendorBO(q.getVendorMemberId(), q.getVendorRoleId())).distinct().collect(Collectors.toList()));
            if(logoResult.getCode() == ResponseCode.SUCCESS.getCode() && CollectionUtils.isEmpty(logoResult.getData())) {
                queryResult.stream().filter(query -> query.getShopId().equals(entry.getKey())).forEach(query -> logoResult.getData().stream().filter(logo -> logo.getVendorMemberId().equals(query.getVendorMemberId()) && logo.getVendorRoleId().equals(query.getVendorRoleId())).findFirst().ifPresent(logo -> query.setLogo(logo.getLogo())));
            }
        }
    }
}
